package io.elegant.widgets

import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Spinner
import com.google.protobuf.Any
import io.elegant.*
import io.elegant.sessions.BaseSession
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlin.reflect.KClass

class SpinnerWidget<T: Spinner>(
    private val session: BaseSession,
    private val group: ViewGroup,
    private val cs: CoroutineScope
): BaseWidget<T>(session, group, cs) {
    override fun createView(clazz: KClass<T>, vararg argv: Any): T? {
        val dialogMode = argv[4].toBoolValue()
        return clazz.constructors.find {
            it.parameters.size > 1
        }?.call(group.context, if (dialogMode) Spinner.MODE_DIALOG
        else Spinner.MODE_DROPDOWN)
    }
    override fun onReceive(name: String, sessionId: Long, futureId: Long, vararg argv: Any): Boolean {
        if (when (name) {
                "getPrompt" -> getPrompt(sessionId, futureId)
                "setPrompt" -> setPrompt(*argv)
                "select" -> select(*argv)
                "setItems" -> setItems(*argv)
                "setOnItemSelectedListener" -> setOnItemSelectedListener(*argv)
                else -> null
        } == null)
            return super.onReceive(name, sessionId, futureId, *argv)
        return true
    }
    private fun getPrompt(sessionId: Long, futureId: Long) {
        val prompt = view?.prompt?.toString()
        onGetPrompt(prompt.toAny(), sessionId, futureId)
    }
    private fun onGetPrompt(prompt: Any, sessionId: Long, futureId: Long) = session.apply {
        sendAction("onGetPrompt", sessionId, futureId, prompt)
    }
    private fun setPrompt(vararg argv: Any) {
        view?.prompt = argv[0].toStringValueOrNull()
    }
    private fun setItems(vararg argv: Any) {
        view?.apply {
            val items = argv.map { it.toStringValue() }
            adapter = ArrayAdapter(context, android.R.layout.simple_spinner_item, items).apply {
                setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
            }
        }
    }
    private fun setOnItemSelectedListener(vararg argv: Any) = object: AdapterView.OnItemSelectedListener {
        override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) = cs.launch {
            session.apply {
                argv[0].sendCallback(p2.toAny())
            }
        }.let { Unit }
        override fun onNothingSelected(p0: AdapterView<*>?) {}
    }.let(view!!::setOnItemSelectedListener)
    private fun select(vararg argv: Any) {
        val index = argv[0].toIntValue()
        view?.setSelection(index)
    }
}